'use strict';

var ctrl = module.exports = {};
var service = require('./wechat.service'),
  co = require('co'),
  Wechat = require('co-wechat'),
  Oauth = require('co-wechat-oauth'),
  Api = require('co-wechat-api'),
  webot = require('webot'),
  _ = require('underscore')._,
  debug = require('debug'),
  log = debug('yozh:mo:wechat:log'),
  error = debug('yozh:mo:wechat:error'),
  verbose = debug('yozh:mo:wechat:verbose'),
  userService = require('../user/user.service'),
  packageInfo = require('../../package.json'),
  config = require('../../config/config'),
  cache = require('../../lib/cache')(config.tokenCache),
  sessCache = require('../../lib/cache')(config.sessionCache),
  run = require('../../lib/run')(),
  search = require('../../lib/support').search,
  geo2loc = require('../../lib/support').geo2loc,
  myRob = require('../../config/my_rob')({webot: webot}),
  robruleService = require('./robrule.service'),
  participle = require('../../config/participle')();

var api = new Api(
  config.weChat.appid,
  config.weChat.appsecret,
  service.getToken(cache, config.weChatAccessToken),
  service.setToken(cache, config.weChatAccessToken)
);

var oauth = new Oauth(
  config.weChat.appid,
  config.weChat.appsecret,
  service.getOpenIdToken(cache),
  service.setOpenIdToken(cache)
);

var propMap = {
  FromUserName: 'uid',
  ToUserName: 'sp',
  CreateTime: 'createTime',
  MsgId: 'id',
  MsgType: 'type',
  Content: 'text'
};

var paramMap = {
  Location_X: 'lat',
  Location_Y: 'lng',
  // 上报地理位置事件 Event == LOCATION
  Latitude: 'lat',
  Longitude: 'lng',
};

/**
 * Replacing wechat reply callbacks with ES6 Generators
 * @param  {Object|String} opts wechat server post message
 * @return {Function}      GEnerator function
 */
var webotReplyGenerator = function(opts) {
  if (typeof opts !== 'object') {
    opts = {
      opts: opts
    };
  } else {
    /*var info = {};
    info.sp = opts.ToUserName;
    info.uid = opts.FromUserName;
    info.id = opts.MsgId;
    info.type = opts.MsgType;
    switch(opts.MsgType) {
      case 'text':
        info.text = opts.Content;
        break;
      case 'image':
        info.param.picUrl = opts.PicUrl;
        break;
      case 'voice':
        info.param.mediaId = opts.MediaId;
        info.param.recognition = opts.Recognition;
        info.param.format = opts.Format;
        break;
      case 'video':
        info.param.mediaId = opts.MediaId;
        info.param.thumbMediaId = opts.ThumbMediaId;
        break;
      case 'location':
        info.param.lat = opts.Location_X;
        info.param.lng = opts.Location_Y;
        info.param.scale = opts.Scale;
        // or null
        info.param.label = opts.Label;
        break;
      case 'link':
        info.param.title = opts.Title;
        info.param.description = opts.Description;
        info.param.url = opts.Url;
        break;
      case 'event':
        info.param.event = opts.Event;
        info.param.eventKey = opts.EventKey;
        break;
      case 'shortvideo':
        info.param.mediaId = opts.MediaId;
        info.param.thumbMediaId = opts.ThumbMediaId;
        break;
      default:
        break;
    }*/
    opts = readable(opts, propMap, paramMap);
  }
  verbose('info: ', opts);
  return function *(resume) {
    // Individual user custom rule
    yield webot.reply(opts, resume);
  };
};

var isRun = false;

ctrl.initRob = function *(next) {
  if (!isRun) {
    isRun = true;
    var ruleList = yield robruleService.find({state: 1});
    verbose('ruleList: ', typeof ruleList, ruleList);
    myRob.init(ruleList);
  }
};

ctrl.checkSignature = Wechat(config.weChat).middleware(function *() {
  // if (wechat.checkSignature(this.query, config.weChat.token)) {
  //   this.status = 200;
  //   this.body = this.query.echostr;
  // } else {
  //   this.status = 200;
  //   this.body = 'fail';
  // }
  this.state.skipChectToken = true;
  // yield next;
});

ctrl.reply = Wechat(config.weChat).middleware(function *() {
  var message = this.weixin;
  log(message);
  if (message.MsgType === 'text') {
    // test jieba
    var result = participle.tag(message.Content);
    this.body = {type: 'text', 'content': result};
    return;
  }
  var res = yield service.getOpenIdToken(cache);
  var sess = yield sessCache.get(message.FromUserName);
  sess = JSON.parse(sess);
  if (!sess) {
    sess = {};
    yield sessCache.set(message.FromUserName, JSON.stringify(sess));
  }
  message.Session = sess;
  var msg = readable(message, propMap, paramMap);
  var cbd = null;
  // co(function *() {
  //   cbd = yield webot.reply(msg);
  //   verbose('co: ', cbd);
  // });
  // var cbd = webot.reply(msg, co.wrap(function *(err, info) {
  //   verbose('reply: ', err, info);
  //   return yield {err: err, info: info};
  // }));
  // webot.reply(msg, function(err, info) {
  //   this.body = {type: "text", content: info.reply};
  // });
  cbd = run.runWebotReply(webotReplyGenerator(message));
  // var cbd = run.runWebotReply(function *(resume) {
  //   yield webot.reply({text: message.Content
  //     + ';' + message.FromUserName, openId: message.FromUserName}, resume);
  // });
  verbose('callback: ', cbd, cbd.info.reply, typeof cbd.info.reply);
  if (cbd) {
    if (cbd.info.err === '404') {
      // cbd = run.runWebotReply(webotReplyGenerator({
      //   text: message.Content,
      //   openId: message.FromUserName,
      //   uid: message.FromUserName,
      //   session: sess
      // }));
      // var cbd = run.runWebotReply(function *(resume) {
      //   yield webot.reply({
      //     text: message.Content,
      //     openId: message.FromUserName
      //   }, resume);
      // });
    }
    yield sessCache.set(message.FromUserName, JSON.stringify(cbd.info.session));
    // this.body = {type: "text", content: JSON.stringify(cbd.info.reply)};
    var replyRes = yield cbd.info.reply;
    verbose('reply res: ', replyRes);
    this.body = {type: "text", content: replyRes};
  } else {
    this.body = {type: "text", content: 'nothing!'};
  }
  if (!res && 0) {
    this.body = {
      type: "text",
      content: 'please binding your account, <a href="' +
        this.request.protocol + '://' + this.request.hostname +
        '/v1/wechat/oauth">click this oauth</a>'
    };
  } else {
    /*switch(message.MsgType) {
      case 'text':
        this.body = {type: "text", content: 'this is text message'};
        this.body = yield service.handleText(message);

        break;
      case 'image':
        // yield;
        this.body = {type: "text", content: 'this is image message'};
        break;
      case 'voice':
        // yield;
        this.body = {type: "text", content: 'this is voice message'};
        break;
      case 'video':
        // yield;
        this.body = {type: "text", content: 'this is video message'};
        break;
      case 'location':
        // yield;
        this.body = {type: "text", content: 'this is location message'};
        break;
      case 'link':
        // yield;
        this.body = {type: "text", content: 'this is link message'};
        break;
      case 'event':
        // yield;
        this.body = {type: "text", content: 'this is event message'};
        break;
      case 'shortvideo':
        // yield;
        this.body = {type: "text", content: 'this is shortvideo message'};
        break;
      default:
        // yield;
        this.body = {type: "text", content: 'this is unknow message'};
    }*/
  }
  // this.status = 200;
});

ctrl.getOauth = function *(next) {
  var url = this.request.protocol +
      '://' +
      this.request.hostname +
     '/v1/wechat/oauthback';
  var path = oauth.getAuthorizeURL(url, '', 'snsapi_userinfo');
  // var path = oauth.getAuthorizeURLForWebsite(url, '', 'snsapi_userinfo');
  this.redirect(path);
  this.state.skipChectToken = true;
  yield next;
};

ctrl.getOauthBack = function *(next) {
  var query = this.query;
  var code = query.code;
  log(code);
  var data = yield oauth.getAccessToken(code);
  log(data);
  if (data) {
    // query user model, width openId = data.openid;
    var user = userService.findUserByOpenId(data.openid);
    if (user) {
      // check user wechat field infornation
      if (userService.isNeedUpdateWechatInfo(user)) {
        var userInfo = yield oauth.getUser(data.openid);
        var res = userService.updateWechatInfo(user, userInfo);
      }
      // redirect index
      this.redirect('/index');
    } else {
      // not binding wechat, redirect to login and register used openId
      this.redirect('/v1/login');
    }
  }
  this.state.skipChectToken = true;
  yield next;
};

/**
 * convert weixin props into more human readable names
 */
function readable(original, pmap, mmap) {
  var param = {};
  var data = {
    raw: original,
    param: param
  };
  var key, val;
  for (key in original) {
    // The body of a for in should be wrapped in an if statement
    // to filter unwanted properties from the prototype
    if (original) {
      val = original[key];
      if (key in pmap) {
        data[pmap[key]] = val;
      } else if (key in mmap) {
        // 名字特殊处理的参数
        param[mmap[key]] = val;
      } else {
        // 其他参数都是将首字母转为小写
        key = key[0].toLowerCase() + key.slice(1);
        if (key === 'recognition') {
          data.text = val;
        }
        param[key] = val;
      }
    }
  }
  data.createTime = new Date(parseInt(data.createTime, 10) * 1000);
  // for compatibility
  data.created = data.createTime;
  data.textBak = data.text;
  data.text += config.rulePrefix + data.uid;
  return data;
}
